package com.stars.easyms.rest.handler;

import com.stars.easyms.alarm.EasyMsAlarmService;
import com.stars.easyms.base.util.ApplicationContextHolder;
import com.stars.easyms.feign.exception.BusinessFeignException;
import com.stars.easyms.rest.bean.RestInfo;
import com.stars.easyms.rest.dto.EasyMsRestRequestEntity;
import com.stars.easyms.rest.exception.BusinessRestAlarmException;
import com.stars.easyms.rest.exception.BusinessRestException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.UndeclaredThrowableException;

/**
 * <p>className: EasyMsRestExceptionHandler</p>
 * <p>description: EasyMs的rest接口的异常信息处理类</p>
 *
 * @author guoguifang
 * @version 1.6.1
 * @date 2020/8/24 4:06 下午
 */
final class EasyMsRestExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(EasyMsRestExceptionHandler.class);

    private final EasyMsAlarmService easyMsAlarmService;

    EasyMsRestExceptionHandler() {
        this.easyMsAlarmService = ApplicationContextHolder.getApplicationContext().getBean(EasyMsAlarmService.class);
    }

    void handleRestAlarmException(Throwable throwable) {
        // 获取rest接口信息
        EasyMsRestRequestEntity restRequestEntity = EasyMsRestSynchronizationManager.getCurrentRestRequestEntity();
        RestInfo restInfo = restRequestEntity.getRestInfo();

        // 如果是未申报的异常类型则获取实际异常
        if (throwable instanceof UndeclaredThrowableException) {
            throwable = ((UndeclaredThrowableException) throwable).getUndeclaredThrowable();
        }

        // 记录异常信息
        boolean isBusinessRestException = throwable instanceof BusinessRestException;
        boolean isBusinessFeignException = throwable instanceof BusinessFeignException;
        if (restInfo != null) {
            // 只有restInfo不为空时才会有BusinessRestException
            if (isBusinessRestException) {
                BusinessRestException businessRestException = (BusinessRestException) throwable;
                if (businessRestException.getCause() != null) {
                    logger.error("Rest Service [{}] execute business failure! Error message: {}",
                            restInfo.getRestServiceClass().getName(), businessRestException.getRetMsg(), businessRestException.getCause());
                } else {
                    // 如果是BusinessRestException并且不是由其他异常引发则使用info级别
                    logger.info("Rest Service [{}] execute business failure! Error message: {}",
                            restInfo.getRestServiceClass().getName(), businessRestException.getRetMsg());
                }
            } else if (isBusinessFeignException) {
                BusinessFeignException businessFeignException = (BusinessFeignException) throwable;
                // 如果是BusinessFeignException则使用info级别
                logger.info("Rest Service [{}] execute feign failure! Error message: {}",
                        restInfo.getRestServiceClass().getName(), businessFeignException.getRetMsg());
            } else {
                logger.error("Rest Service [{}] execute failure!", restInfo.getRestServiceClass().getName(), throwable);
            }
        } else {
            logger.error("Handle Rest Service execute failure!", throwable);
        }

        // 判断是否需要告警，告警异常为BusinessRestAlarmException或者非BusinessRestException及非BusinessFeignException
        boolean isBusinessRestAlarmException = throwable instanceof BusinessRestAlarmException;
        boolean isNeedAlarm = isBusinessRestAlarmException || (!isBusinessRestException && !isBusinessFeignException);
        if (isNeedAlarm && easyMsAlarmService.canAlarm()) {
            easyMsAlarmService.sendExceptionAlarmMessage(throwable);
        }
    }

}